package com.endurance.compoent;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * JDK动态代理技术
 */
@Component
public class TransactionProxyFactory2 {

    @Autowired
    private TransactionManager transactionManager;

    // Spring 容器
    @Autowired
    ApplicationContext applicationContext;

    /**
     * @param cls (传递过来被代理类的字节码)可以利用传递过来的字节码对象获取实现的接口, 类加载器,
     * @return 例如:传递过来的ProductServiceImpl.class,将来该方法就返回传递过来的ProductServiceImpl的代理对象
     */
    public Object createProxyInstance(Class cls) {

        // 判断传递过来的被代理类是否实现了接口
        if (cls.getInterfaces().length > 0) {
            return Proxy.newProxyInstance(cls.getClassLoader(),
                    cls.getInterfaces(),
                    new InvocationHandler() {
                        /**
                         *
                         * @param proxy 底层生成的代理对象
                         * @param method 通过代理对象调用方法封装成mehtod对象
                         * @param args 通过代理类对象调用的方法传递的参数
                         * @return
                         * @throws Throwable
                         */
                        @Override
                        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                            Object retVal = null;
                            // 如果不是查询方法才加入事务管理
                            if (!method.getName().startsWith("find")) {
                                try {
                                    transactionManager.beginTransaction();
                                    // applicationContext.getBean(cls) 根据Bean的类型去获取该Bean
                                    // 相当于new 一个对象调用该对象的方法
                                    retVal = method.invoke(applicationContext.getBean(cls), args);
                                    transactionManager.commit();
                                } catch (Exception e) {
                                    e.printStackTrace();
                                    transactionManager.rollback();
                                } finally {
                                    transactionManager.release();
                                }
                            }
                            return retVal;
                        }
                    });
        } else {
            // 如果该类没有实现任何接口，使用DCLIB动态代理
            //1. 利用Enhancer增强被代理类,通过它生成代理类
            Enhancer enhancer = new Enhancer();
            //2. 设置代理类的父类
            enhancer.setSuperclass(cls);
            //3. 设置回调函数,当通过代理类对象调用方法,转调回调函数
            enhancer.setCallback(new MethodInterceptor() {
                /**
                 *
                 * @param o 代理类对象
                 * @param method 通过代理类对象调用的方法封装成Method对象
                 * @param args 通过代理对象调用的方法传递参数
                 * @param methodProxy 底层生成的代理类
                 * @return
                 * @throws Throwable
                 */
                @Override
                public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
                    Object retVal = null;
                    // 如果不是查询方法才加入事务管理
                    if (!method.getName().startsWith("find")) {
                        try {
                            transactionManager.beginTransaction();
                            // applicationContext.getBean(cls) 根据Bean的类型去获取该Bean
                            // 相当于new 一个对象调用该对象的方法
                            retVal = method.invoke(applicationContext.getBean(cls), args);
                            transactionManager.commit();
                        } catch (Exception e) {
                            e.printStackTrace();
                            transactionManager.rollback();
                        } finally {
                            transactionManager.release();
                        }
                    }
                    return retVal;
                }
            });
            // 返回当前代理对象
            return enhancer.create();
        }

    }

}
